import {ServerResponse} from "http"
import {LogFactory} from "../../support/log"
import {StaticResourceManager} from "../../manager/StaticResourceManager"
import * as fs from "fs"
import * as mime from "mime"

export class HttpResponseFacade{
  logger = LogFactory.getLogger("HttpResponse")
  private readonly response: ServerResponse
  private readonly request: HttpRequest
  readonly startTime: number
  private readonly inject: any
  private lock: boolean = false

  constructor(serverResponse: ServerResponse, inject: any = {}) {
    // @ts-ignore
    this.response = serverResponse
    this.request = serverResponse.req as HttpRequest
    this.inject = inject
    this.startTime = +new Date()
  }

  private setEnd() {
    this.lock = true
  }

  closed() {
    return this.response.writableEnded || this.lock
  }

  end(data, code = 200) {
    if(this.closed() || this.lock){
      this.logger.warn(`socket closed, write fail:`, data)
      return
    }
    this.setEnd()
    if (typeof data !== "string"){
      data = JSON.stringify(data)
      this.response.setHeader("content-type", "application/json;charset=utf-8")
    } else {
      this.response.setHeader("content-type", "text/html; charset=UTF-8")
    }
    this.response.statusCode = code

    this.response.end(data, () => {
      const {statusMessage, req} = this.response
      const {url} = req
      const time = + new Date() - this.startTime
      this.logger.info(`[${url}] ${time}ms ${code}`)
    })
  }

  getStaticResource(path: string) {
    return StaticResourceManager.getStaticResource(path)
  }

  resource(path: string) {
    const file = this.getStaticResource(path)
    if(file) {
      this.setEnd()
      try {
        const mimeType = mime.getType(file)
        this.response.setHeader("Content-Type", mimeType)
      }catch (e) {
      }
      fs.createReadStream(file).pipe(this.response)
      return true
    } else {
      throw new Error("not found")
    }
  }

  sendRedirect(path: string, data: any = "") {
    if(this.closed()) {
      return
    }
    this.response.setHeader("content-type", "text/html; charset=UTF-8")
    // 以http开头和 /开头为绝对路径, 否则为相对路径
    this.response.setHeader("location", path)
    this.end(data, 302)
  }

  forward(path: string) {
    const url = this.request.url
    this.logger.info(`[${url}] forward to [${path}]`)
    this.request.url = path
    this.inject.forward(this.request, this.response)
  }

  error(statusCode: number, msg: string = "") {
    let formatMsg
    if(this.request.isJson) {
      formatMsg = {
        code: statusCode,
        msg
      }
    }else{
      formatMsg = msg
    }
    this.end(formatMsg, statusCode)
  }
}



